package com.lp.biz.coupon.service.impl;
import java.time.LocalDateTime;
import java.math.BigDecimal;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.lp.biz.coupon.mapper.BizCouponMemberRelMapper;
import com.lp.biz.coupon.model.entity.BizCoupon;
import com.lp.biz.coupon.mapper.BizCouponMapper;
import com.lp.biz.coupon.model.entity.BizCouponMemberRel;
import com.lp.biz.coupon.model.query.CouponQuery;
import com.lp.biz.coupon.model.vo.*;
import com.lp.biz.coupon.service.BizCouponService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lp.biz.member.mapper.MemberMapper;
import com.lp.biz.member.model.entity.Member;
import com.lp.biz.message.service.BizMessageSystemService;
import com.lp.common.exception.BaseException;
import com.lp.common.utils.CommonResult;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

import static com.lp.common.constant.CommonConstant.NEGATE;
import static com.lp.common.constant.CommonConstant.SURE;
import static com.lp.common.constant.CouponConstant.*;
import static com.lp.common.utils.Tools.copyPage;
import static com.lp.common.utils.Tools.stripTrailingZeros;

/**
 * @program: backend
 * @description: BizCoupon 服务实现类
 * @author Ke.Song
 * @since 2024-07-21 23:38:11
 */
@Service
public class BizCouponServiceImpl extends ServiceImpl<BizCouponMapper, BizCoupon> implements BizCouponService {

    @Autowired
    private MemberMapper memberMapper;

    @Autowired
    private BizCouponMemberRelMapper relMapper;

    @Autowired
    private BizMessageSystemService messageSystemService;

    @Override
    public CommonResult getCouponList(CouponQuery query) {
        LambdaQueryWrapper<BizCoupon> queryWrapper = new QueryWrapper<BizCoupon>().lambda()
                .eq(BizCoupon::getIsDeleted, NEGATE)
                .eq(BizCoupon::getIsEnable, SURE)
                .orderByDesc(BizCoupon::getCreateAt);
        if (query.getUseType() != null) {
            queryWrapper.eq(BizCoupon::getUseType, query.getUseType());
        }
        if (StringUtils.isNotBlank(query.getCreateAt())) {
            queryWrapper.between(BizCoupon::getCreateAt, query.getCreateAt() + " 00:00:00",
                    query.getCreateAt() + " 23:59:59");
        }
        PageHelper.startPage(query.getPage(), query.getSize());
        List<BizCoupon> list = list(queryWrapper);
        Page<CouponList> couponLists = copyPage(new Page<>(), list);
        for (BizCoupon bizCoupon : list) {
            couponLists.add(CouponList.builder(bizCoupon));
        }
        return CommonResult.restPage(couponLists);
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public void addCoupon(CouponAdd params) {
        Integer gainType = params.getGainType();
        Integer useType = params.getUseType();
        BigDecimal amount = params.getAmount();
        BigDecimal condition = params.getCondition();
        Integer validityDays = params.getValidityDays();
        if (!gainType.equals(GAIN_TYPE_NEW) && !gainType.equals(GAIN_TYPE_TRAINING) && !gainType.equals(GAIN_TYPE_MEMBERS)
                && !gainType.equals(GAIN_TYPE_BIRTHDAY) && !gainType.equals(GAIN_TYPE_COURSE)) {
            throw new BaseException("获取方式输入错误");
        }
        if (!useType.equals(USE_TYPE_GENERIC) && !useType.equals(USE_TYPE_TRAINING) && !useType.equals(USE_TYPE_MEMBERS)
                && !useType.equals(USE_TYPE_COURSE)) {
            throw new BaseException("使用类型输入错误");
        }
        if (amount.compareTo(BigDecimal.ZERO) <= 0) {
            throw new BaseException("额度输入错误");
        }
        if (condition.compareTo(BigDecimal.ZERO) <= 0 || condition.compareTo(amount) <= 0) {
            throw new BaseException("使用限制输入错误");
        }
        if (validityDays < 0) {
            throw new BaseException("有效时间输入错误");
        }
        BizCoupon bizCoupon = new BizCoupon();
        bizCoupon.setAmount(amount);
        bizCoupon.setCondition(condition);
        bizCoupon.setGainType(gainType);
        bizCoupon.setUseType(useType);
        bizCoupon.setValidityDays(validityDays);
        bizCoupon.setIsEnable(SURE);
        bizCoupon.setCreateAt(LocalDateTime.now());
        bizCoupon.setIsDeleted(NEGATE);
        save(bizCoupon);
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public void deleteCoupon(Integer couponId) {
        BizCoupon coupon = getById(couponId);
        if (coupon == null || coupon.getIsDeleted().equals(SURE)) {
            throw new BaseException("优惠券输入错误");
        }
        relMapper.update(null, new UpdateWrapper<BizCouponMemberRel>().lambda()
                .eq(BizCouponMemberRel::getBizCouponId, coupon.getId())
                .eq(BizCouponMemberRel::getStatus, STATUS_NOT_USED)
                .set(BizCouponMemberRel::getStatus, STATUS_INVALID)
                .set(BizCouponMemberRel::getUpdateAt, LocalDateTime.now()));
        coupon.setIsDeleted(SURE);
        updateById(coupon);
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public void specifyMember(SpecifyCouponAdd params) {
        Member member = memberMapper.selectById(params.getMemberId());
        if (member == null) {
            throw new BaseException("用户输入错误");
        }
        Integer useType = params.getUseType();
        BigDecimal amount = params.getAmount();
        BigDecimal condition = params.getCondition();
        Integer validityDays = params.getValidityDays();
        if (amount.compareTo(BigDecimal.ZERO) <= 0) {
            throw new BaseException("额度输入错误");
        }
        if (!useType.equals(USE_TYPE_GENERIC) && !useType.equals(USE_TYPE_TRAINING) && !useType.equals(USE_TYPE_MEMBERS)
                && !useType.equals(USE_TYPE_COURSE)) {
            throw new BaseException("使用类型输入错误");
        }
        if (condition.compareTo(BigDecimal.ZERO) <= 0 || condition.compareTo(amount) <= 0) {
            throw new BaseException("使用限制输入错误");
        }
        if (validityDays < 0) {
            throw new BaseException("有效时间输入错误");
        }
        BizCouponMemberRel rel = new BizCouponMemberRel();
        rel.setBizMemberId(member.getId());
        rel.setAmount(amount);
        rel.setCondition(condition);
        rel.setType(useType);
        rel.setStartAt(LocalDateTime.now());
        rel.setEndAt(rel.getStartAt().plusDays(validityDays));
        rel.setStatus(STATUS_NOT_USED);
        rel.setIsDeleted(NEGATE);
        rel.setCreateAt(rel.getStartAt());
        rel.setUpdateAt(rel.getStartAt());
        rel.setValidityDays(validityDays);
        relMapper.insert(rel);
        messageSystemService.addCoupon(member.getId());
    }

    @Override
    public CommonResult getSpecifyCoupon(CouponQuery query) {
        PageHelper.startPage(query.getPage(), query.getSize());
        List<SpecifyCouponList> specifyCoupon = relMapper.getSpecifyCoupon(query);
        for (SpecifyCouponList o : specifyCoupon) {
            o.setAmount(stripTrailingZeros(o.getAmount()));
            o.setCondition(stripTrailingZeros(o.getCondition()));
        }
        return CommonResult.restPage(specifyCoupon);
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public void deleteSpecifyCoupon(Integer couponId) {
        BizCouponMemberRel rel = relMapper.selectById(couponId);
        if (rel == null || rel.getIsDeleted().equals(SURE)) {
            throw new BaseException("优惠券输入错误");
        }
        if (rel.getStatus().equals(STATUS_USED) || rel.getStatus().equals(STATUS_INVALID)) {
            throw new BaseException("不能删除");
        }
        rel.setIsDeleted(SURE);
        relMapper.updateById(rel);
    }

    @Override
    public CommonResult getCouponSummary() {
        CouponSummary summary = new CouponSummary();
        for (BizCouponMemberRel rel : relMapper.selectList(new QueryWrapper<BizCouponMemberRel>().lambda()
                .eq(BizCouponMemberRel::getIsDeleted, NEGATE))) {
            summary.setTotal(summary.getTotal() + 1);
            if (rel.getStatus().equals(STATUS_NOT_USED)) {
                summary.setNotUseTotal(summary.getNotUseTotal() + 1);
            } else if (rel.getStatus().equals(STATUS_USED)) {
                summary.setUseTotal(summary.getUseTotal() + 1);
            } else if (rel.getStatus().equals(STATUS_INVALID)) {
                summary.setInvalidTotal(summary.getInvalidTotal() + 1);
            }
        }
        return CommonResult.success(summary);
    }

    @Override
    public CommonResult getUseCouponList(CouponQuery query) {
        PageHelper.startPage(query.getPage(), query.getSize());
        List<UseCouponList> useCouponList = relMapper.getUseCouponList(query);
        for (UseCouponList couponList : useCouponList) {
            couponList.setAmount(stripTrailingZeros(couponList.getAmount()));
            couponList.setCondition(stripTrailingZeros(couponList.getCondition()));
        }
        return CommonResult.restPage(useCouponList);
    }

    @Override
    public CommonResult getNotUseCouponList(CouponQuery query) {
        PageHelper.startPage(query.getPage(), query.getSize());
        List<NotUseCouponList> notUseCouponList = relMapper.getNotUseCouponList(query);
        for (NotUseCouponList useCouponList : notUseCouponList) {
            useCouponList.setAmount(stripTrailingZeros(useCouponList.getAmount()));
            useCouponList.setCondition(stripTrailingZeros(useCouponList.getCondition()));
        }
        return CommonResult.restPage(notUseCouponList);
    }
}
